const csr = @import("csr");

pub fn lock() void {
    csr.clear(.mstatus, .{ .mie = true });
}

pub fn unlock() void {
    csr.set(.mstatus, .{ .mie = true });
}

pub const SpinLock = struct {
    state: State,

    const State = enum(u8) {
        unlocked,
        locked,
    };

    pub const Held = struct {
        spinlock: *SpinLock,

        pub fn release(self: Held) void {
            @atomicStore(State, &self.spinlock.state, .unlocked, .release);
        }
    };

    pub fn init() SpinLock {
        return .{ .state = .unlocked };
    }

    pub fn deinit(self: *SpinLock) void {
        self.* = undefined;
    }

    pub fn tryAcquire(self: *SpinLock) ?Held {
        return switch (@atomicRmw(State, &self.state, .Xchg, .locked, .acquire)) {
            .unlocked => .{ .spinlock = self },
            .locked => null,
        };
    }

    pub fn acquire(self: *SpinLock) Held {
        while (true) {
            return self.tryAcquire() orelse {
                continue;
            };
        }
    }
};
